#ifndef UNIVERSAL_CALL_H_INCLUDED
#define UNIVERSAL_CALL_H_INCLUDED

namespace com{
    namespace example{
        namespace testone{
            namespace template_{



// general template form
template<class Callable>
struct universal_call;

// partial specialisation to cover most cases
template<class R, class...Args>
struct universal_call<R(Args...)> {
    template<class Callable>
    universal_call(Callable&& callable)
    : _impl { std::make_shared<model<Callable>>(std::forward<Callable>(callable)) }
    {}

    R operator()(Args&&...args) const {
        return _impl->call(std::forward<Args>(args)...);
    }
private:
    struct concept {
        virtual R call(Args&&...args) = 0;
        virtual ~concept() = default;
    };

    template<class Callable>
    struct model : concept {
        model(Callable&& callable)
        : _callable(std::move(callable))
        {}
        R call(Args&&...args) override {
            return _callable(std::forward<Args>(args)...);
        }
        Callable _callable;
    };

    std::shared_ptr<concept> _impl;
};

// pathalogical specialisation for std::packaged_task -
// erases the return type from the signature
template<class R, class...Args>
struct universal_call<std::packaged_task<R(Args...)>>
: universal_call<void(Args...)>
{
    using universal_call<void(Args...)>::universal_call;
};

// (possibly) helpful function
template<class F>
universal_call<F> make_universal_call(F&& f)
{
    return universal_call<F>(std::forward<F>(f));
}



            }
        }
    }
}



#endif // UNIVERSAL_CALL_H_INCLUDED
